<template>
  <Upload.Dragger
    v-model:file-list="fileList"
    accept=".xlsx, .xls"
    :maxCount="1"
    :beforeUpload="() => false"
    @change="handleInputClick"
    @drop="handleInputClick"
    @remove="remove"
    @reject="
      () => {
        createMessage.warning('只能上传.xlsx文件');
      }
    "
  >
    <Icon icon="ant-design:cloud-upload-outlined" />
    <p>点击或者拖拽文件导入</p>
  </Upload.Dragger>
</template>
<script lang="ts" name="ImportExcel" setup>
  import type { UploadProps } from 'ant-design-vue';
  import { Upload } from 'ant-design-vue';
  import { ref } from 'vue';
  import * as XLSX from 'xlsx';

  import Icon from '@/components/Icon/Icon.vue';
  import { useMessage } from '@/hooks/web/useMessage';
  import { dateUtil } from '@/utils/dateUtil';

  import type { ExcelData } from './typing';

  const props = defineProps({
    dateFormat: {
      type: String,
      default: '',
    },
    timeZone: {
      type: Number,
      default: 8,
    },
    isReturnFile: {
      type: Boolean,
      default: false,
    },
  });
  const emit = defineEmits(['success', 'error']);
  const { createMessage } = useMessage();
  const excelDataSource = ref<any[]>([]);
  const fileList = ref<UploadProps['fileList']>([]);

  function getHeaderRow(sheet: XLSX.WorkSheet) {
    if (!sheet || !sheet['!ref']) return [];
    const headers: string[] = [];
    const range = XLSX.utils.decode_range(sheet['!ref']);

    const R = range.s.r;
    for (let C = range.s.c; C <= range.e.c; ++C) {
      const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })];
      let hdr = 'UNKNOWN ' + C;
      if (cell && cell.t) hdr = XLSX.utils.format_cell(cell);
      headers.push(hdr);
    }
    return headers;
  }
  function getExcelData(workbook: XLSX.WorkBook) {
    const excelData: ExcelData[] = [];
    const { dateFormat, timeZone } = props;
    for (const sheetName of workbook.SheetNames) {
      const worksheet = workbook.Sheets[sheetName];
      const header: string[] = getHeaderRow(worksheet);
      let results = XLSX.utils.sheet_to_json(worksheet, {
        raw: true,
        dateNF: dateFormat,
      }) as object[];
      results = results.map((row: object) => {
        for (const field in row) {
          if (row[field] instanceof Date) {
            if (timeZone === 8) {
              row[field].setSeconds(row[field].getSeconds() + 43);
            }
            if (dateFormat) {
              row[field] = dateUtil(row[field]).format(dateFormat);
            }
          }
        }
        return row;
      });

      excelData.push({
        header,
        results,
        meta: {
          sheetName,
        },
      });
    }
    return excelData;
  }

  // 读取xlsx文件
  function readerData(rawFile: File) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = async (e) => {
        try {
          const data = e.target && e.target.result;
          const workbook = XLSX.read(data, { type: 'array', cellDates: true });
          const excelData = getExcelData(workbook);
          excelDataSource.value.splice(0, excelDataSource.value.length, ...excelData[0].results);
          emit('success', { ...excelData }, rawFile);
          fileList.value?.splice(0, fileList.value.length);
          resolve('');
        } catch (error) {
          reject(error);
          emit('error');
        }
      };
      reader.readAsArrayBuffer(rawFile);
    });
  }

  // 上传文件触发事件
  async function handleInputClick(target) {
    const files = target?.fileList;
    const rawFile = (files && files[0]) || target?.file;
    if (!rawFile) return;
    if (props.isReturnFile) {
      emit('success', rawFile);
      return;
    }
    await readerData(rawFile.originFileObj);
  }

  const remove = () => {
    emit('success', []);
    return true;
  };
</script>
